package keqiang.com.kq_flutter_core_widget.util.dingtalk;

import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.dingtalk.share.ddsharemodule.DDShareApiFactory;
import com.android.dingtalk.share.ddsharemodule.IDDAPIEventHandler;
import com.android.dingtalk.share.ddsharemodule.IDDShareApi;
import com.android.dingtalk.share.ddsharemodule.message.*;
import com.keqiang.base.Logger;
import keqiang.com.kq_flutter_core_widget.BuildConfig;
import keqiang.com.kq_flutter_core_widget.util.ErrCode;

import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;


/**
 * 提供与微信操作Api
 *
 * @author Created by wanggaowan on 2024/12/18 下午3:52
 */
public class DDAPI {
    private static final String TAG = DDAPI.class.getSimpleName();
    private static DDAPI mDDApi;
    
    private final String mAppId;
    private final IDDShareApi mApi;
    /**
     * 是否已经向钉钉注册过且注册成功
     */
    private boolean registerApp;
    private final DDApiEventHandlerImpl mEventHandler = new DDApiEventHandlerImpl();
    
    private DDAPI(@NonNull Context context, @NonNull String appId) {
        mAppId = appId;
        mApi = DDShareApiFactory.createDDShareApi(context, appId, !BuildConfig.DEBUG);
        registerApp();
    }
    
    @NonNull
    static DDAPI getApi(@NonNull Context context, @NonNull String appId) {
        if (mDDApi == null || !appId.equals(mDDApi.mAppId)) {
            mDDApi = new DDAPI(context, appId);
        }
        return mDDApi;
    }
    
    /**
     * 向微信注册App
     */
    private void registerApp() {
        if (registerApp) {
            return;
        }
        
        registerApp = mApi.registerApp(mAppId);
    }
    
    static void handIntent(@Nullable Intent intent) {
        DDAPI api = DDAPI.mDDApi;
        if (api == null) {
            return;
        }
        
        if (intent == null) {
            api.mEventHandler.onResp(null);
            return;
        }
        
        try {
            api.mApi.handleIntent(intent, api.mEventHandler);
        } catch (Exception e) {
            Logger.printStackTrace(e);
        }
    }
    
    private static void parseLoginResp(BaseResp baseResp, LoginCallback callback) {
        if (!(baseResp instanceof SendAuth.Resp)) {
            callback.callback(ErrCode.FAILED, null);
            Logger.e(TAG, "授权失败");
            return;
        }
        
        SendAuth.Resp resp = (SendAuth.Resp) baseResp;
        if (!Objects.equals(resp.state, resp.mTransaction)) {
            // 钉钉返回state与本地发送state不一致，可能被篡改
            callback.callback(ErrCode.FAILED, null);
            Logger.e(TAG, "授权不可靠");
        } else if (resp.mErrCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
            callback.callback(ErrCode.CANCEL, null);
            Logger.e(TAG, "用户取消授权");
        } else if (resp.mErrCode != BaseResp.ErrCode.ERR_OK) {
            callback.callback(ErrCode.FAILED, null);
            Logger.e(TAG, "授权失败");
        } else {
            Logger.e(TAG, "授权成功");
            callback.callback(ErrCode.SUCCESS, resp.code);
        }
    }
    
    private static void parseShareResp(BaseResp baseResp, Callback callback) {
        if (!(baseResp instanceof SendMessageToDD.Resp)) {
            callback.callback(ErrCode.FAILED);
            Logger.e(TAG, "授权失败");
            return;
        }
        
        SendMessageToDD.Resp resp = (SendMessageToDD.Resp) baseResp;
        if (resp.mErrCode == BaseResp.ErrCode.ERR_USER_CANCEL) {
            callback.callback(ErrCode.CANCEL);
            Logger.e(TAG, "用户取消授权");
        } else if (resp.mErrCode != BaseResp.ErrCode.ERR_OK) {
            callback.callback(ErrCode.FAILED);
            Logger.e(TAG, "授权失败");
        } else {
            Logger.e(TAG, "授权成功");
            callback.callback(ErrCode.SUCCESS);
        }
    }
    
    public static void authLogin(@NonNull Context context, @NonNull String appId, @NonNull LoginCallback callback) {
        DDAPI api = DDAPI.getApi(context, appId);
        int code = checkApi(api);
        if (code != ErrCode.SUCCESS) {
            callback.callback(code, null);
            return;
        }
        
        String mToken = UUID.randomUUID().toString();
        SendAuth.Req req = new SendAuth.Req();
        req.scope = SendAuth.Req.SNS_LOGIN;
        req.mTransaction = mToken;
        req.state = mToken;
        
        boolean success = api.mApi.sendReq(req);
        if (success) {
            RespCallback respCallback = new RespCallback() {
                @Override
                public void callback(@Nullable BaseResp baseResp) {
                    api.mEventHandler.unregisterOnWXRespCallback(this);
                    parseLoginResp(baseResp, callback);
                }
            };
            api.mEventHandler.registerOnWXRespCallback(respCallback);
        }
    }
    
    private static int checkApi(DDAPI api) {
        if (!api.registerApp) {
            api.registerApp();
        }
        
        if (!api.registerApp) {
            Logger.e(TAG, "程序注册到钉钉失败");
            return ErrCode.FAILED;
        }
        
        if (!api.mApi.isDDAppInstalled()) {
            Logger.e(TAG, "app未安装");
            return ErrCode.APP_NOT_INSTALL;
        }
        return ErrCode.SUCCESS;
    }
    
    public static void shareTextData(@NonNull Context context, @NonNull String appId, @NonNull String content,
                                     String title, String msgContent, String msgUrl, byte[] icon, String iconUrl, Callback callback) {
        DDTextMessage textObject = new DDTextMessage();
        textObject.mText = content;
        shareData(context, appId, textObject, title, msgContent, msgUrl, icon, iconUrl, callback);
    }
    
    public static void shareWebData(@NonNull Context context, @NonNull String appId, @NonNull String url,
                                    String title, String msgContent, String msgUrl, byte[] icon, String iconUrl, Callback callback) {
        DDWebpageMessage webpage = new DDWebpageMessage();
        webpage.mUrl = url;
        shareData(context, appId, webpage, title, msgContent, msgUrl, icon, iconUrl, callback);
    }
    
    public static void shareImageData(@NonNull Context context, @NonNull String appId, String localPath,
                                      byte[] bytes, String url, Callback callback) {
        DDImageMessage message = new DDImageMessage();
        message.mImageData = bytes;
        message.mImagePath = localPath;
        message.mImageUrl = url;
        shareData(context, appId, message, null, null, null, null, null, callback);
    }
    
    public static void shareData(@NonNull Context context, @NonNull String appId, @NonNull DDMediaMessage.IMediaObject mediaObject,
                                 String title, String msgContent, String msgUrl, byte[] icon, String iconUrl, Callback callback) {
        DDAPI api = DDAPI.getApi(context, appId);
        int code = checkApi(api);
        if (code != ErrCode.SUCCESS) {
            callback.callback(code);
            return;
        }
        
        DDMediaMessage msg = new DDMediaMessage(mediaObject);
        msg.mTitle = title;
        msg.mContent = msgContent;
        msg.mUrl = msgUrl;
        msg.mThumbData = icon;
        msg.mThumbUrl = iconUrl;
        
        String mToken = UUID.randomUUID().toString();
        SendMessageToDD.Req req = new SendMessageToDD.Req();
        req.mMediaMessage = msg;
        req.mTransaction = mToken;
        
        boolean success = api.mApi.sendReq(req);
        if (!success) {
            if (callback != null) {
                callback.callback(ErrCode.FAILED);
            }
            return;
        }
        
        if (callback != null) {
            RespCallback respCallback = new RespCallback() {
                @Override
                public void callback(@Nullable BaseResp baseResp) {
                    api.mEventHandler.unregisterOnWXRespCallback(this);
                    parseShareResp(baseResp, callback);
                }
            };
            api.mEventHandler.registerOnWXRespCallback(respCallback);
        }
    }
    
    public interface LoginCallback {
        /**
         * @param code     授权结果：{@link ErrCode}
         * @param authCode 授权码，失败时为null
         */
        void callback(int code, String authCode);
    }
    
    public interface Callback {
        /**
         * @param code 授权结果：{@link ErrCode}
         */
        void callback(int code);
    }
    
    private interface RespCallback {
        void callback(@Nullable BaseResp baseResp);
    }
    
    private static class DDApiEventHandlerImpl implements IDDAPIEventHandler {
        private final ArrayList<RespCallback> onRespCallbacks = new ArrayList<>();
        
        public void registerOnWXRespCallback(RespCallback on) {
            this.onRespCallbacks.add(on);
        }
        
        public void unregisterOnWXRespCallback(RespCallback on) {
            this.onRespCallbacks.remove(on);
        }
        
        @Override
        public void onReq(BaseReq baseReq) {
        
        }
        
        @Override
        public void onResp(BaseResp baseResp) {
            ArrayList<RespCallback> callbacks = new ArrayList<>(onRespCallbacks);
            for (RespCallback callback : callbacks) {
                callback.callback(baseResp);
            }
        }
    }
}

